package com.demo.common.exception;

import com.demo.common.utils.JsonResult;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

@Log4j2
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    //运行时异常
    @ExceptionHandler(RuntimeException.class)
    public JsonResult runtimeExceptionHandler(RuntimeException ex) {
        return resultFormat(ex);
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public JsonResult nullPointerExceptionHandler(NullPointerException ex) {
        return resultFormat(ex);
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public JsonResult classCastExceptionHandler(ClassCastException ex) {
        return resultFormat(ex);
    }

    //IO异常
    @ExceptionHandler(IOException.class)
    public JsonResult iOExceptionHandler(IOException ex) {
        return resultFormat(ex);
    }

    //未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public JsonResult noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        return resultFormat(ex);
    }

    //数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public JsonResult indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        return resultFormat(ex);
    }

    //400错误
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public JsonResult requestNotReadable(HttpMessageNotReadableException ex) {
        return resultFormat(ex);
    }

    //400错误
    @ExceptionHandler({TypeMismatchException.class})
    public JsonResult requestTypeMismatch(TypeMismatchException ex) {
        return resultFormat(ex);
    }

    //400错误
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public JsonResult requestMissingServletRequest(MissingServletRequestParameterException ex) {
        return resultFormat(ex);
    }

    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public JsonResult request405(HttpRequestMethodNotSupportedException ex) {
        return resultFormat(ex);
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public JsonResult request406(HttpMediaTypeNotAcceptableException ex) {
        return resultFormat(ex);
    }

    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public JsonResult server500(RuntimeException ex) {
        return resultFormat(ex);
    }

    //栈溢出
    @ExceptionHandler({StackOverflowError.class})
    public JsonResult requestStackOverflow(StackOverflowError ex) {
        return resultFormat(ex);
    }

    //除数不能为0
    @ExceptionHandler({ArithmeticException.class})
    public JsonResult arithmeticException(ArithmeticException ex) {
        log.info(ex.getMessage());
        return resultFormat(ex);
    }


    //其他错误
    @ExceptionHandler({Exception.class})
    public JsonResult exception(Exception ex) {
        return resultFormat(ex);
    }

    //服务错误
    @ExceptionHandler({ServiceException.class})
    public JsonResult serviceException(ServiceException ex) {
        return JsonResult.err(ex.getErrorCode(), ex.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public JsonResult methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        return JsonResult.err(ex.getBindingResult().getFieldError().getDefaultMessage());
    }

    private <T extends Throwable> JsonResult resultFormat(T ex) {
        ex.printStackTrace();
        return JsonResult.err(ex.getMessage());
    }


}
